package com.weifly.weistock.rotation;

import com.weifly.weistock.rotation.bo.RotationConfigBO;
import com.weifly.weistock.rotation.bo.RotationPointBO;
import com.weifly.weistock.core.market.StockMarketService;
import com.weifly.weistock.core.market.StockPriceDto;
import com.weifly.weistock.core.monitor.MonitorConstants;
import com.weifly.weistock.core.task.AbstractUpdateService;
import com.weifly.weistock.core.task.UpdateStatus;
import com.weifly.weistock.core.util.DateUtils;
import com.weifly.weistock.core.util.WeistockUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

/**
 * 轮动监控逻辑处理
 *
 * @author weifly
 * @since 2020/12/02
 */
public class RotationCheckAction {

    private Logger log = LoggerFactory.getLogger(RotationCheckAction.class);

    private StockMarketService stockMarketService;

    private RotationMonitorService rotationMonitorService;

    public void setStockMarketService(StockMarketService stockMarketService) {
        this.stockMarketService = stockMarketService;
    }

    public void setRotationMonitorService(RotationMonitorService rotationMonitorService) {
        this.rotationMonitorService = rotationMonitorService;
    }

    public void checkIfNeed(UpdateStatus updateStatus) {
        // 更新状态
        this.rotationMonitorService.updateStatus(updateStatus);

        // 执行检查
        if (updateStatus.getPreStatus() == AbstractUpdateService.STATUS_INIT) {
            this.check();
        } else if (updateStatus.getStatus() == AbstractUpdateService.STATUS_RUN) {
            updateStatus.setSleepTime(5000); // 5秒执行一次
            int todayTime = updateStatus.getCheckHour() * 3600000 + updateStatus.getCheckMinute() * 60000 + updateStatus.getCheckSecond() * 1000;
            if (MonitorConstants.TIME_9HOUR_0MINUTE <= todayTime && todayTime < MonitorConstants.TIME_9HOUR_15MINUTE) {
                // 清空前一天的下单记录
                this.rotationMonitorService.clearMonitorInfo();
            }
            if (MonitorConstants.TIME_9HOUR_15MINUTE <= todayTime && todayTime <= MonitorConstants.TIME_15HOUR_3MINUTE) {
                // 监控
                this.check();
            }
        }
    }

    public void check() {
        RotationConfigBO rotationConfig = rotationMonitorService.getRotationConfig();
        if (!rotationConfig.isOpen()) {
            this.rotationMonitorService.writeMessage("不监控...");
            return;
        }
        this.rotationMonitorService.writeMessage("开始更新...");

        Double baseStockPrice = this.getStockPrice(rotationConfig.getBaseStockCode());
        if (baseStockPrice == null) {
            return;
        }
        Double compareStockPrice = this.getStockPrice(rotationConfig.getCompareStockCode());
        if (compareStockPrice == null) {
            return;
        }

        RotationPointBO pointBO = this.calcPointInfo(rotationConfig, baseStockPrice, compareStockPrice);
        log.info("轮动监控数据：" + WeistockUtils.toJsonString(pointBO));
        this.rotationMonitorService.addRotationPoint(pointBO);
    }

    private Double getStockPrice(String stockCode) {
        StockPriceDto priceDto = this.stockMarketService.getStockPrice(stockCode);
        if (priceDto == null) {
            this.rotationMonitorService.writeMessage("无法获得价格: " + stockCode);
            return null;
        }
        if (priceDto.getNowPrice() != null && priceDto.getNowPrice() > 0) {
            return priceDto.getNowPrice();
        }
        if (priceDto.getYesterdayClosePrice() != null && priceDto.getYesterdayClosePrice() > 0) {
            return priceDto.getYesterdayClosePrice();
        }
        this.rotationMonitorService.writeMessage("无法获得价格: " + WeistockUtils.toJsonString(priceDto));
        return null;
    }

    private RotationPointBO calcPointInfo(RotationConfigBO rotationConfig, Double baseStockPrice, Double compareStockPrice) {
        BigDecimal baseNormalValue = this.calcNormalizationValue(baseStockPrice, rotationConfig.getBaseStockPrice());
        BigDecimal compareNormalValue = this.calcNormalizationValue(compareStockPrice, rotationConfig.getCompareStockPrice());
        BigDecimal diffValue = compareNormalValue.subtract(baseNormalValue);

        RotationPointBO pointBO = new RotationPointBO();
        pointBO.setTime(DateUtils.formatTime(new Date()));
        pointBO.setBasePrice(baseStockPrice);
        pointBO.setBaseNormal(baseNormalValue.doubleValue());
        pointBO.setComparePrice(compareStockPrice);
        pointBO.setCompareNormal(compareNormalValue.doubleValue());
        pointBO.setDiff(diffValue.doubleValue());
        return pointBO;
    }

    // 计算归一化值
    private BigDecimal calcNormalizationValue(Double now, Double base) {
        BigDecimal nowValue = new BigDecimal(now).multiply(new BigDecimal(100));
        BigDecimal baseValue = new BigDecimal(base);
        return nowValue.divide(baseValue, 4, RoundingMode.HALF_UP);
    }
}
